let logger = require('./logger').logger,
    cfg = require('../config.json'),
    Client = require('bitcoin-core'),
    pg = require('../db/db');
let client;
// init client 
let initClient = async () => {
    try {
        client = new Client(cfg.bitCfg);
        if (typeof client == 'undefined') {
            client = new Client(cfg.bitCfg);
        }
        logger.info('bitcoin client init success.');
    } catch (error) {
        logger.error("client init error===>", error);
    }
}
// writer transaction to db
async function insertTxs(blockInfo) {
    if (blockInfo.height != 0) {
        for (const txid of blockInfo.tx) {
            let txhash = await pg.any(`SELECT txid FROM bittransactions WHERE bittransactions."txid" = '${txid}'`);
            if (txhash.length == 0) {
                let rawtx = await client.getRawTransaction(txid, true).catch((error) => {
                    logger.error('getRawTransaction method error:==>', error);
                    pg.none(`INSERT INTO errtx(txid) VALUES ('${txid}');`);
                    global.gc();
                });
                global.gc();
                await handle_tx_sql(rawtx);
                await handle_utxo_sql(rawtx);
                logger.info(`the current block: ${blockInfo.height} txid: ${txid} write database success.`);
            } else {
                logger.info(`the current block: ${blockInfo.height} txid: ${txid} is already exists in database.`);
            }
            global.gc();
        }
        return 'finished';
        global.gc();
    }
}
let handle_tx_sql = async (txs) => {
    let sql_filed = `INSERT INTO bittransactions(txid, hash, version, size, vsize, locktime, vin, vout, hex `;
    let sql_value = `VALUES ('${txs.txid}', '${txs.hash}', ${txs.version}, ${txs.size}, ${txs.vsize}, 
      ${txs.locktime}, '${JSON.stringify(txs.vin)}', '${JSON.stringify(txs.vout)}', '${txs.hex}'`;

    if (txs.blockhash !== undefined) {
        sql_filed += `, blockhash, confirmations, "time", blocktime)`;
        sql_value += `, '${txs.blockhash}' , '${txs.confirmations}' , '${txs.time}', '${txs.blocktime}')`;
    } else {
        sql_filed += `)`;
        sql_value += `)`;
    }
    await pg.none(sql_filed + sql_value);
    global.gc();
}

let handle_utxo_sql = async (txs) => {
    for (const element of txs.vout) {
        let sql = `INSERT INTO utxos(
              txid, value, n, asm, hex, "reqSigs", type, addresses, isused)
              VALUES ('${txs.txid}', '${element.value}',
              ${element.n}, '${element.scriptPubKey.asm}', 
                      '${element.scriptPubKey.hex}', '${element.scriptPubKey.reqSigs == undefined ? "" : element.scriptPubKey.reqSigs}', 
                      '${element.scriptPubKey.type}', '${element.scriptPubKey.addresses == undefined ? "" : element.scriptPubKey.addresses}', null);`;
        await pg.none(sql);
        global.gc();
    }
}

//receive message from main process
process.on('message', async (message) => {
    try {
        if (client == undefined) {
            initClient();
        }
        // logger.info('main process:', message)
        const rest = await insertTxs(message.blockInfo);
        //send message to main process
        process.send({ counter: rest });
    } catch (error) {
        logger.error('child process error:', error);
        initClient();
    }
})
